﻿using System;
using System.Windows.Input;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Collections.ObjectModel;
using Microsoft.Practices.Prism.Commands;
using System.Windows.Controls;
using System.Windows;
using Microsoft.Win32;

using App_pressing_Loreau.Helper;
using App_pressing_Loreau.Data.DAO;
using App_pressing_Loreau.Model.DTO;
using App_pressing_Loreau.Model;
using App_pressing_Loreau.Data;


namespace App_pressing_Loreau.ViewModel
{
    /// <summary>
    /// ViewModel pour la vue NouvelleCommande.xaml
    /// Classe permettant l'enregistrement d'une nouvelle commande,
    /// l'affichage les articles par département
    /// la possibilité de supprimer un article sélectionné
    /// </summary>
    class NouvelleCommandeVM : ObservableObject
    {


        #region Attributs

        //public int payeDifferer = 0;

        private List<CategoryItem> _listeDepartement;
        private List<CategoryItem> _listeArticles;
        private List<Departement> listeDepartementDTO = null;
        private List<TypeArticle> articlesByDep = null;
        private TypeArticle typeArticleDTO = null;

        private float _label_NouvelleCommande_prixTotal;
        public float prixTotal { get; private set; }

        private DelegateCommand<ArticlesVM> _deleteArticles;
        private List<Article> lArticles;
        private bool commandePayeeEnDiffere;
        private List<PlaceConvoyeur> liste_d_emplacements_occupés_par_cette_commande;

        #endregion


        #region Constructeur
        public NouvelleCommandeVM()
        {

            lArticles = new List<Article>();

            defileDepartementPrecedente();
            prixTotal = 0;
            if (ContentDetailCommande != null)
            {
                for (int i = 0; i < ContentDetailCommande.Count; i++)
                {
                    Label_NouvelleCommande_prixTotal += (ContentDetailCommande[i].typeArticle.TTC);
                }

            }

            //Initialisation de la liste d'emplacements vides
            ClasseGlobale.PlacesLibres.setList(PlaceConvoyeurDAO.selectConvoyeursEmpty());
            commandePayeeEnDiffere = false;
            ClasseGlobale._contentDetailCommande = null;


            liste_d_emplacements_occupés_par_cette_commande = new List<PlaceConvoyeur>();

        }

        #endregion


        #region Proprietés et Commandes

        //gestion du choix des articles

        #region Commandes
        //Ajouter un article a la commande 
        ICommand listesArticlesCommandes;
        public ICommand ListesArticlesCommandes
        {
            get
            {
                if (ClasseGlobale._contentDetailCommande != null)
                    return listesArticlesCommandes ?? (listesArticlesCommandes = new RelayCommand(AjouterArticles));
                else return null;
            }

        }
        #endregion

        #region Bouton departement
        //Permet de faire réagir le bouton
        ICommand onButtonClickCommand;

        public ICommand OnButtonClickCommand
        {
            get { return onButtonClickCommand ?? (onButtonClickCommand = new RelayCommand(Contenudepartement)); }
        }




        public ICommand CommandeSuivante
        {
            get
            {
                return new RelayCommand(p => defileDepartementSuivante(),
                    p => ListeDepartements.Count != 4);
            }
        }

        public ICommand CommandePrecedente
        {
            get
            {
                return new RelayCommand(p => defileDepartementPrecedente(),
                    p => ListeDepartements.Count != 6);
            }
        }

        public List<CategoryItem> ListeDepartements
        {
            get
            {
                return _listeDepartement;
            }
            set
            {
                _listeDepartement = value;
                RaisePropertyChanged("ListeDepartements");
            }
        }

        public List<CategoryItem> ListeArticles
        {
            get
            {
                return _listeArticles;
            }
            set
            {
                _listeArticles = value;
                RaisePropertyChanged("ListeArticles");
            }
        }
        #endregion


        #region contenu commande

        public float Label_NouvelleCommande_prixTotal
        {
            get { return _label_NouvelleCommande_prixTotal; }
            set
            {
                if (value != _label_NouvelleCommande_prixTotal)
                {
                    _label_NouvelleCommande_prixTotal = value;
                    OnPropertyChanged("Label_NouvelleCommande_prixTotal");
                }
            }
        }


        public ObservableCollection<ArticlesVM> ContentDetailCommande
        {
            get
            {
                if (commandePayeeEnDiffere == false)
                {
                    if (ClasseGlobale._contentDetailCommande == null)
                    {
                        ClasseGlobale.initializeContentDetailCommande();
                    }
                }

                return ClasseGlobale._contentDetailCommande;

            }
            set
            {
                if (value != null)
                {
                    ClasseGlobale._contentDetailCommande = value;
                    OnPropertyChanged("ContentDetailCommande");
                }
            }
        }

        public DelegateCommand<ArticlesVM> DeleteArticles
        {
            get
            {
                if (commandePayeeEnDiffere == false)
                    return this._deleteArticles ?? (this._deleteArticles = new DelegateCommand<ArticlesVM>(
                                                                           this.ExecuteDeleteArticles,
                                                                           (arg) => true));
                else
                {
                    MessageBox.Show("L'édition de la commande précédente est terminée, veuillez retourner à l'accueil");
                    return null;
                }
            }
        }


        #endregion


        #region paiement differé
        public ICommand Btn_PaiementDiffere
        {
            get { return new RelayCommand(p => paiementDiffere()); }
        }

        // Insertion de la commande et des articles concernants dans la bdd pour un paiment différé
        private void paiementDiffere()
        {
            if (ClasseGlobale.Client.nom != "")
            {
                if (ClasseGlobale._contentDetailCommande == null)
                {
                    MessageBox.Show("Ajoutez des articles");
                }
                else
                {

                    Commande cmd = new Commande(DateTime.Now, false, 0, ClasseGlobale.Client);

                    //ObservableCollection<ArticlesVM> listeArticles = ClasseGlobale._contentDetailCommande;
                    if (CommandeDAO.insertCommande(cmd) == 1)
                    {
                        cmd = CommandeDAO.lastCommande();
                        foreach (ArticlesVM artVM in ClasseGlobale._contentDetailCommande)
                        {
                            ArticleDAO.insertArticle(artVM.getArticle(cmd.id));
                        }

                        //Mise à jour de la table convoyeur
                        foreach (PlaceConvoyeur place in ClasseGlobale.PlacesLibres.getList())
                        {
                            PlaceConvoyeurDAO.updatePlaceConvoyeur(place);
                        }

                        MessageBox.Show("La commande " + cmd.id + " à été enregistrée avec succès");

                        //Clear l'écran et bloque l'utilisation des touches


                        try
                        {
                            cmd = CommandeDAO.selectCommandeById(cmd.id, true, true, true);
                            RecuPaiement rp = new RecuPaiement(cmd);
                            rp.printRecu();
                            rp.printRecu();
                            //impression des tickets vetements
                            if (cmd.listArticles != null)
                            {
                                TicketVetement ticketVetement = new TicketVetement(cmd);
                                ticketVetement.printAllArticleCmd();
                            }
                            else
                                MessageBox.Show("La commande ne contient pas d'articles");
                        }
                        catch (Exception)
                        {
                            MessageBox.Show("Impression refusée");
                        }
                        finally
                        {
                            ClasseGlobale.SET_ALL_NULL();
                            commandePayeeEnDiffere = true;
                        }
                    }
                    else
                    {
                        MessageBox.Show("Erreur lors de la création de la commande. Enregistrement de la commande annulé");
                    }

                }


            }
            else
            {
                MessageBox.Show("La comande a déjà été enregistrée. Veuillez cliquer sur HOME");
            }

        }


        #endregion

        #endregion


        #region Méthodes


        /**
         * Permet le défilement des départements 
         **/

        public void defileDepartementPrecedente()
        {
            ListeDepartements = new List<CategoryItem>();
            listeDepartementDTO = (List<Departement>)DepartementDAO.selectDepartements();


            if (listeDepartementDTO != null)
            {
                for (int i = 0; i < 6; i++)
                    ListeDepartements.Add(new CategoryItem() { ButtonContent = listeDepartementDTO[i].nom, ButtonTag = listeDepartementDTO[i].id });
            }

        }

        public void defileDepartementSuivante()
        {
            ListeDepartements = new List<CategoryItem>();

            if (listeDepartementDTO != null)
            {

                for (int i = 6; i < listeDepartementDTO.Count; i++)
                    ListeDepartements.Add(new CategoryItem() { ButtonContent = listeDepartementDTO[i].nom, ButtonTag = listeDepartementDTO[i].id });
            }

        }

        /**
         * Permet d'afficher  les articles correspondants à un département
         * */
        private void Contenudepartement(object button)
        {
            Button clickedbutton = button as Button;
            List<CategoryItem> listedesArticles = new List<CategoryItem>();
            articlesByDep = new List<TypeArticle>();
            articlesByDep = (List<TypeArticle>)TypeArticleDAO.selectTypeByDepId(Int32.Parse(clickedbutton.Tag.ToString()));

            if (articlesByDep.Count > 0)
            {
                if (clickedbutton != null)
                {
                    int x = 15, y = 5;

                    foreach (TypeArticle type in articlesByDep)
                    {
                        listedesArticles.Add(new CategoryItem() { ButtonArticlesContent = type.nom, ButtonArticlesTag = type.id, X = x, Y = y });
                        if (x < 16) { x = 220; }
                        else if (x < 221) { x = 425; }
                        else if (x > 424)
                        {
                            x = 15;
                            y += 70;
                        }
                    }
                    ListeArticles = listedesArticles;
                }
            }
            else
            {
                MessageBox.Show("Departement vide");
            }

        }

        public void AjouterArticles(object button)
        {

            if (ClasseGlobale._contentDetailCommande != null)
            {
                Button clickedbutton = button as Button;
                if (clickedbutton != null)
                {
                    typeArticleDTO = (TypeArticle)TypeArticleDAO.selectTypesById(Int32.Parse(clickedbutton.Tag.ToString()));

                    PlaceConvoyeur place = new PlaceConvoyeur();
                    place = null;
                    

                    if (typeArticleDTO.encombrement == 0 || typeArticleDTO.encombrement > 3)
                    {
                        //Cet article ne va pas dans le convoyeur
                    }
                    else
                    {
                        //Je parcours la liste pour trouver une place convoyeur pouvant accueillir l'article
                        int finDeListe = ClasseGlobale.PlacesLibres.getList().Count();
                        float encombrement_occupe_pour_cette_place;
                        float encombrement_maximum = 3 - typeArticleDTO.encombrement;
                        for (int i = 0; i < finDeListe; i++)
                        {

                            //si l'encombrement du convoyeur est permet de recevoir l'article
                            encombrement_occupe_pour_cette_place = ClasseGlobale.PlacesLibres.getList()[i].encombrement;

                            //###########################################################################################################
                            //D'abord, je regarde s'il y à un emplacement vide pouvant recevoir toute la commande
                            //Aussi j'ai une variable de classe contenant la liste des emplacement utilisés pour cette commande


                            //###########################################################################################################
                            // Si la place est vide je peux le mettre
                            if (encombrement_occupe_pour_cette_place == 0)
                            {
                                //Je modifie l'encombrement de la place convoyeur
                                ClasseGlobale.PlacesLibres[i].encombrement += typeArticleDTO.encombrement;
                                //Je récupère la place convoyeur concernée
                                place = ClasseGlobale.PlacesLibres.getList()[i];
                                liste_d_emplacements_occupés_par_cette_commande.Add(place);
                                break;
                            }
                            // Mais si la place ne l'est pas, je dois vérifier que 
                            //  - l'emplacement peut accueilllir cet article
                            //  - les articles déjà présents appartiennent à la même commande (s'il y a déjà un article à cet emplacement, alors la place est contenue dans la liste)
                            else if (encombrement_occupe_pour_cette_place <= encombrement_maximum && liste_d_emplacements_occupés_par_cette_commande.Contains(ClasseGlobale.PlacesLibres.getList()[i]))
                            {
                                //Je modifie l'encombrement de la place convoyeur
                                ClasseGlobale.PlacesLibres[i].encombrement += typeArticleDTO.encombrement;
                                //Je récupère la place convoyeur concernée
                                place = ClasseGlobale.PlacesLibres.getList()[i];
                                break;
                            }


                            if (i == finDeListe - 1)
                            {
                                // à la dernière occurence de la boucle, si il me reste toujours des articles à placer, je reparcours la liste en ne 
                                // considérant plus que les articles d'une commande ne doivent pas être mélangés à d'autres


                                for (int j = 0; j < finDeListe; j++)
                                {
                                    //si l'encombrement du convoyeur est permet de recevoir l'article
                                    encombrement_occupe_pour_cette_place = ClasseGlobale.PlacesLibres.getList()[j].encombrement;

                                    if (encombrement_occupe_pour_cette_place <= encombrement_maximum)
                                    {
                                        //Je modifie l'encombrement de la place convoyeur
                                        ClasseGlobale.PlacesLibres[j].encombrement += typeArticleDTO.encombrement;
                                        //Je récupère la place convoyeur concernée
                                        place = ClasseGlobale.PlacesLibres.getList()[j];
                                        break;
                                    }
                                    if (j == finDeListe - 1)
                                    {
                                        MessageBox.Show("Cet article ne trouve pas sa place dans le convoyeur.\n" +
                                                        "Peut-être n'y a t-il plus de place ou cet article est trop volumineux pour les emplacements restants.");
                                    }
                                }
                            }
                        }
                    }


                    //On construit un nouvel ArticlesVM
                    ArticlesVM articleVmAAjouter = new ArticlesVM()
                    {
                        typeArticle = typeArticleDTO,
                        ArticlesName = typeArticleDTO.nom,
                        PlaceConvoyeur = place
                    };
                    ClasseGlobale._contentDetailCommande.Add(articleVmAAjouter);
                    //ClasseGlobale._contentDetailCommande.Contains(articleVmAAjouter);

                    Label_NouvelleCommande_prixTotal = 0;
                    decimal tampon = 0;
                    foreach (ArticlesVM artVm in ClasseGlobale._contentDetailCommande)
                    {
                        tampon += (decimal)(artVm.typeArticle.TTC);
                    }
                    Label_NouvelleCommande_prixTotal = (float)tampon;//(float)Math.Round(tampon, 2, MidpointRounding.AwayFromZero);// 
                }
            }
        }
        private void ExecuteDeleteArticles(ArticlesVM artVM)
        {
            if (ClasseGlobale._contentDetailCommande != null)
            {
                if (ClasseGlobale._contentDetailCommande.Contains(artVM))
                {
                    //Modif de la liste place convoyeur
                    //mettre à jour la  liste convoyeur
                    //J'ai l'id de l'article => je récupe l'id conv => je met à jour l'encombrement

                    //Je parcours la  liste de place libre pour trouver l'id conv qui convient
                    int finDeListe = ClasseGlobale.PlacesLibres.getList().Count();

                    if (artVM.PlaceConvoyeur != null)//Si égal à null cela veut dire qu'aucun emplacement convoyeur n'a été atribué
                    {
                        for (int i = 0; i < finDeListe; i++)
                        {
                            // la condition est vrai quand j'ai trouvé l'emplacement convoyeur qui a été attribué à mon article
                            if (ClasseGlobale.PlacesLibres.getList()[i].id == artVM.PlaceConvoyeur.id)
                            {
                                //Je modifie l'encombrement de la liste des places libres
                                ClasseGlobale.PlacesLibres[i].encombrement -= typeArticleDTO.encombrement;
                                //Si l'emplacement à été vidé, je le supprime de la liste des emplecements en cours
                                if (ClasseGlobale.PlacesLibres[i].encombrement == 0)
                                {
                                    liste_d_emplacements_occupés_par_cette_commande.Remove(ClasseGlobale.PlacesLibres[i]);
                                }
                                break;
                            }
                        }
                    }

                    //Modif du prix total
                    ClasseGlobale._contentDetailCommande.Remove(artVM);
                    decimal tamp = (decimal)Label_NouvelleCommande_prixTotal;
                    tamp -= (decimal)artVM.typeArticle.TTC;
                    Label_NouvelleCommande_prixTotal = (float)tamp;


                }
            }

        }

        #endregion
    }

    #region Class
    public class CategoryItem
    {
        public string ButtonContent { get; set; }
        public string ButtonArticlesContent { get; set; }

        public Brush ButtonDepBackground { get; set; }
        public int ButtonTag { get; set; }
        public int ButtonArticlesTag { get; set; }

        public int X { get; set; }
        public int Y { get; set; }

    }

    #endregion
}
